<?php
declare (strict_types=1);

namespace app\middleware;

use app\factory\Factory;
use app\factory\model\RequestAgreement;
use app\factory\model\ResponseAgreement;
use app\factory\tool\frameVerify\EncryptionTool;
use app\factory\tool\VerifyIsTest;
use app\model\register\User;
use think\facade\Log;
use think\Response;

/**
 * ClassName:加密校验中间件
 * @author leijunxiang
 * @time 2024/8/31
 * @auditor
 */
class EncrypCheck
{

    /**
     * 处理请求
     *
     * @param \think\Request $request
     * @param \Closure $next
     * @return Response
     */
    public function handle($request, \Closure $next)
    {

        if ($request->isPost() || $request->isPut()) {
            $tool = app(VerifyIsTest::TOOL_VERIFY_IS_TEST);
            //是否测试
            $flag = $tool->startVerify($request);
            $contentType = $request->contentType();
            if ($contentType != 'multipart/form-data') {
                $post = $request->post();
                $post = @$post['data'];
                if (empty($post)) {
                    return Response::create(['errMsg' => '约定参数错误，请重试', 'errCode' => FAIL, "content" => []], 'json', 403);
                }
                if (!$flag) {
                    $tool = Factory::getInstance()->getToolObj(EncryptionTool::TOOL_ENCRYPTION_TOOL);
                    //是加密字符串
                    if (empty($post) || is_array($post)) {
                        return Response::create(['errMsg' => '加密验证失败，请重试(1)', 'errCode' => FAIL, "content" => []], 'json', 403);
                    }
                    //base64 解密
                    $decryptData = base64_decode($post);
                    $md5Data = substr($decryptData, -32);
                    $priData = substr($decryptData, 0, -32);
                    //(MD5后数据)MD5（源数据）
                    $md5Encrypt = $tool->md5Encrypt($priData);
                    if ($md5Data != $md5Encrypt) {
                        //验证失败
                        return Response::create(['errMsg' => '加密验证失败，请重试(2)', 'errCode' => FAIL, "content" => []], 'json', 403);
                    }
                    //（解密后数据）AES解密数据（源数据）
                    $data = $tool->aesDecrypt($priData);
                } else {
                    $data = $post;
                }
                //初始化请求对象
                $flag = $this->initRequestObj($data);
                if (!$flag) {
                    return Response::create(['errMsg' => '请求数据不是约定的格式，请重试', 'errCode' => FAIL, "content" => []], 'json', 403);
                }
            }

        }
        //交给下一个处理器处理
        $response = $next($request);
        //初始化返回对象
        $this->initResponseObj($response, $request);
        return $response;
    }

    /**
     * 初始化请求对象
     */
    protected function initRequestObj($data)
    {
        //转化为数组
        if (!is_array($data)) {
            $data = json_decode($data, true);
        }
        $obj = Factory::getInstance()->getModelObj(RequestAgreement::MODEL_REQUEST_AGREEMENT);
        // jsonToObj(数据)
        $obj->jsonToObj($data);
        return true;
    }

    /**
     * 初始化返回对象(返回对象，post数据)
     */
    protected function initResponseObj($response, $request)
    {
        //控制器执行完之后处理
        $responseObj = Factory::getInstance()->getModelObj(ResponseAgreement::MODEL_RESPONSE_AGREEMENT);
        //（属性数组）获取属性
        $arr = $responseObj->getAttribute();
        //清除数据
        $responseObj->__destruct();
//        if(empty($arr['errCode'])){
//            $arr['errCode'] = 200;
//            $arr['errMsg'] = "";
//            $arr['content'] = [];
//        }


        if ($arr['errCode']) {
            $data = json_encode($arr, JSON_UNESCAPED_UNICODE);
            $tool = app(VerifyIsTest::TOOL_VERIFY_IS_TEST);
            //是否测试
            $flag = $tool->startVerify($request);
            if (!$flag) {
                //加密数据
                $data = $this->encrypt($data);
            }

            $response->data($data);
//            $response->code($arr['errCode']);
            $response->code(200);
        }
    }

    /**
     * 加密数据
     * @param $data
     * @return string
     */
    public function encrypt($data)
    {
        $tool = Factory::getInstance()->getToolObj(EncryptionTool::TOOL_ENCRYPTION_TOOL);
        //（加密后数据）AES加密数据（源数据）
        $aesEncrypt = $tool->aesEncrypt($data);
        //(MD5后数据)MD5（源数据）
        $md5Encrypt = $tool->md5Encrypt($aesEncrypt);
        $aesEncrypt .= $md5Encrypt;
        $ecryptData = base64_encode($aesEncrypt);
        return $ecryptData;
    }
}
